package cn.sytton.taffecloud.serivce.auth.security;

import cn.sytton.taffecloud.serivce.auth.security.handler.AuthenticationEntryPointImpl;
import cn.sytton.taffecloud.serivce.auth.security.pwd.UserPwdAuthenticationProvider;
import cn.sytton.taffecloud.serivce.auth.security.sms.SmsCodeAuthenticationProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * SpringSecurity总配置入口
 *
 * @author skyrock
 */
@EnableWebSecurity //加了这个注解，filterChain方法中的httpSecurity就不提示Could not autowire. No beans of 'HttpSecurity' type found
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig {

    /**
     * 认证失败处理类
     */
    @Resource
    private AuthenticationEntryPointImpl authenticationEntryPointImpl;

    /**
     * 短信认证提供者
     */
    @Resource
    private SmsCodeAuthenticationProvider smsCodeAuthenticationProvider;

    /**
     * 用户密码认证提供者
     */
    @Resource
    private UserPwdAuthenticationProvider pwdAuthenticationProvider;

    /**
     * 退出处理类
     */
//    @Resource
//    private LogoutSuccessHandlerImpl logoutSuccessHandlerImpl;


    /**
     * DisableEncodeUrlFilter
     * WebAsyncManagerIntegrationFilter
     * SecurityContextPersistenceFilter
     * CorsFilter
     * LogoutFilter
     * JwtAuthenticationTokenFilter
     * HeaderWriterFilter
     * RequestCacheAwareFilter
     * SecurityContextHolderAwareRequestFilter
     * AnonymousAuthenticationFilter
     * SessionManagementFilter
     * ExceptionTranslationFilter
     * FilterSecurityInterceptor
     * * */
    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity httpSecurity, @Qualifier("customAuthenticationManager") AuthenticationManager customAuthenticationManager) throws Exception {
        httpSecurity
                //启用跨域控制, 配置corsConfigurationSource
                .cors()
                .and()
                // CSRF禁用，因为不使用session
                .csrf().disable()
                // 认证失败处理类
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPointImpl).and()
                // 基于token，所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                // 过滤请求
                .authorizeRequests()
                // 都不要授权
                .anyRequest().permitAll()
                .and()
                .headers().frameOptions().disable().cacheControl().disable();

        httpSecurity.authenticationManager(customAuthenticationManager);

        // 添加Logout filter
//        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandlerImpl);

        return httpSecurity.build();
    }

    @Bean
    protected AuthenticationManager customAuthenticationManager() {
        ProviderManager authenticationManager = new ProviderManager(
                Arrays.asList(
                        smsCodeAuthenticationProvider,
                        pwdAuthenticationProvider
                ));
        //不擦除认证密码，擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
        authenticationManager.setEraseCredentialsAfterAuthentication(false);
        return authenticationManager;
    }

}
